from django.db import models
from django.db.models import signals 
from apscheduler.scheduler import Scheduler
import logging
import traceback
sched = Scheduler()

META_MAP={
    'Cpu Time':'0',
    'JBOSS Version':'1',
    'Start Date':'2',
    'Host':'3',
    'Running Config':'4',
    'Operating System':'5',
    'Free Memory':'6',
    'Max Memory':'7',
    'Total Memory':'8',
    'Threads':'9',
    'JVM Version':'10',
    'CPU':'11'
}
logger = logging.getLogger(__name__)

def jboss_instance_created(sender, instance, created, raw, **kwargs):
    from jboss_observer.analyzer.views import jboss_instances    
    if created == True :
        jboss_instances[instance.pk] =  instance
        sched.add_interval_job(createReport, minutes=instance.track_period,args=[instance.pk],name=instance.pk) 
        createReport(instance.pk)
    else:
        unschedule_observing_job(instance.id)
        sched.add_interval_job(createReport, minutes=instance.track_period,args=[instance.pk],name=instance.pk)
        jboss_instances[instance.pk] =  instance

def jboss_instance_deleted(sender, instance,**kwargs):
    from jboss_observer.analyzer.views import jboss_instances  
    unschedule_observing_job(instance.id)
    del jboss_instances[instance.id]

def unschedule_observing_job(instanceId):
    for job in sched.get_jobs():
        if job.name == instanceId:
            sched.unschedule_job(job)

def createReport(instanceId):
    try:
        from jboss_observer.analyzer.views import jboss_instances
        http_type='http'
        if jboss_instances[instanceId].has_https == True:
            http_type='https'
            
        generate_mem_report(jboss_instances,instanceId,http_type)
        
        generate_meta_report(jboss_instances,instanceId,http_type)
    except Exception:
        logger.error("Error while generating monitoring data. "+traceback.format_exc())
    
def generate_meta_report(jboss_instances,instanceId,http_type):
    import time     
    theurl = http_type+'://'+jboss_instances[instanceId].jmx_page+'/web-console/ServerInfo.jsp'
    
    r1 = prepare_http_response(jboss_instances,instanceId,theurl)
    
    
    meta_map = {}
    meta_map2 = {}
    for l in r1:
        populate_meta(l,meta_map,meta_map2)
             
    
    theurl = http_type+'://'+jboss_instances[instanceId].jmx_page+'/jmx-console/HtmlAdaptor?action=invokeOpByName&name=jboss.system%3Atype%3DServerInfo&methodName=listThreadCpuUtilization'
    
    r1 = prepare_http_response(jboss_instances,instanceId,theurl)
    
    thread_list=""
    for l in r1:
        populate_meta2(l,meta_map)
        if jboss_instances[instanceId].track_threads == True:
            if l.find('<th>Thread Name</th>')!= -1:
                thread_list=l
    
    meta_report=Meta_Report();
    if jboss_instances[instanceId].track_threads == True:
        meta_report.meta_data_thread=populate_thread_meta(thread_list)
    j_inst = Jboss_Instance.objects.get(pk=instanceId)
    j_inst.meta_data=meta_map2
    j_inst.save()
    
    meta_report.jboss_instance=j_inst
    meta_report.meta_data=meta_map
    meta_report.report_date=time.time()
    meta_report.save()
    #print meta_map
    #print meta_map2

def populate_meta(s,meta_map,meta_map2):
    if s.find('<b>Version: </b>')!= -1:
        meta_map2[META_MAP['JBOSS Version']]=s.split("<b>Version: </b>")[1].split(" ")[0]
    elif s.find('<b>Start date: </b>')!= -1:
        meta_map2[META_MAP['Start Date']]=s.split("<b>Start date: </b>")[1].split("<")[0]
    elif s.find('<b>Host: </b>')!= -1:
        meta_map2[META_MAP['Host']]=s.split("<b>Host: </b>")[1].split("<")[0]
    elif s.find('<b>Running config: </b>')!= -1:
        meta_map2[META_MAP['Running Config']]=s.split("<b>Running config: </b>")[1].split("<")[0]
    elif s.find('<b>#CPU: </b>')!= -1:
        meta_map2[META_MAP['CPU']]=s.split("<b>#CPU: </b>")[1].split("<")[0]
    elif s.find('<b>OS: </b>')!= -1:
        meta_map2[META_MAP['Operating System']]=s.split("<b>OS: </b>")[1].split("<")[0]
    elif s.find('<b>Free Memory: </b>')!= -1:
        meta_map[META_MAP['Free Memory']]=formatVal(s.split("<b>Free Memory: </b>")[1].split("<")[0])
    elif s.find('<b>Max Memory: </b>')!= -1:
        meta_map[META_MAP['Max Memory']]=formatVal(s.split("<b>Max Memory: </b>")[1].split("<")[0])
    elif s.find('<b>Total Memory: </b>')!= -1:
        meta_map[META_MAP['Total Memory']]=formatVal(s.split("<b>Total Memory: </b>")[1].split("<")[0])
    elif s.find('<b>#Threads: </b>')!= -1:
        meta_map[META_MAP['Threads']]=s.split("<b>#Threads: </b>")[1].split("<")[0]
    elif s.find('<b>JVM Version: </b>')!= -1:
        meta_map2[META_MAP['JVM Version']]=s.split("<b>JVM Version: </b>")[1].split(" ")[0]

def populate_meta2(s,meta_map):
    if s.find('<td>Total</td>')!= -1:
        meta_map[META_MAP['Cpu Time']]=s.split("<td>Total</td>")[1].replace("<td>","").replace("</td></tr></table>","").replace("\r\n","")

def populate_thread_meta(thread_list):
    thread_list=thread_list.replace("<table><tr><th>Thread Name</th><th>CPU (milliseconds)</th></tr><tr><td>", "")
    thread_list=thread_list.replace("<tr>", "")
    thread_list=thread_list.replace("</td>", "")
    thread_list=thread_list.replace("</tr>", "")
    thread_list=thread_list.replace("</table>", "")
    if thread_list.find('<>') == -1:
        return thread_list.replace("<td>","<>")
def generate_mem_report(jboss_instances,instanceId,http_type):
    import time 

    theurl = http_type+'://'+jboss_instances[instanceId].jmx_page+'/jmx-console/HtmlAdaptor?action=invokeOpByName&name=jboss.system%3Atype%3DServerInfo&methodName=listMemoryPools&argType=boolean&arg0=True'
    
    r1 = prepare_http_response(jboss_instances,instanceId,theurl)
    
    
    j_inst=Jboss_Instance()
    j_inst.pk=instanceId
    
    for l in r1:
        if l.find('Total Memory Pools') != -1 :
            report=Report()
            report.report_date=time.time()

            l=l.replace("-", "")
            l=l.replace("/", "")
            l=l.replace(" ", "")
            l=l.split("<b>")
            #TODO sayilari check et ve refactor et burayi
            maxx=l[4].split("max")[3].split(":")[1]
            used=l[4].split("max")[3].split(":")[2]
            
            maxx=formatVal(maxx[0:maxx.index("<")])
            used=formatVal(used[0:used.index("<")])
            
            report.jboss_instance=j_inst
            report.mem_max_1=maxx
            report.mem_cur_1=used
            
            maxx=l[6].split("max")[3].split(":")[1]
            used=l[6].split("max")[3].split(":")[2]
            
            maxx=formatVal(maxx[0:maxx.index("<")])
            used=formatVal(used[0:used.index("<")])
            
            report.mem_max_2=maxx
            report.mem_cur_2=used
            
            maxx=l[8].split("max")[3].split(":")[1]
            used=l[8].split("max")[3].split(":")[2]
            
            maxx=formatVal(maxx[0:maxx.index("<")])
            used=formatVal(used[0:used.index("<")])
            
            report.mem_max_3=maxx
            report.mem_cur_3=used
            
            maxx=l[10].split("max")[3].split(":")[1]
            used=l[10].split("max")[3].split(":")[2]
            
            maxx=formatVal(maxx[0:maxx.index("<")])
            used=formatVal(used[0:used.index("<")])
            
            report.mem_max_4=maxx
            report.mem_cur_4=used
            
            maxx=l[12].split("max")[3].split(":")[1]
            used=l[12].split("max")[3].split(":")[2]
            
            maxx=formatVal(maxx[0:maxx.index("<")])
            used=formatVal(used[0:used.index("<")])
            
            report.mem_max_5=maxx
            report.mem_cur_5=used
            
            report.save()

def prepare_http_response(jboss_instances,instanceId,theurl):
    import urllib2
    if jboss_instances[instanceId].has_security == True:
        username = jboss_instances[instanceId].username
        password = jboss_instances[instanceId].password
        # a great password
        
        passman = urllib2.HTTPPasswordMgrWithDefaultRealm()
        # this creates a password manager
        passman.add_password(None, theurl, username, password)
        # because we have put None at the start it will always
        # use this username/password combination for  urls
        # for which `theurl` is a super-url
        
        authhandler = urllib2.HTTPBasicAuthHandler(passman)
        # create the AuthHandler
        
        opener = urllib2.build_opener(authhandler)
        
        urllib2.install_opener(opener)
        # All calls to urllib2.urlopen will now use our handler
        # Make sure not to include the protocol in with the URL, or
        # HTTPPasswordMgrWithDefaultRealm will be very confused.
        # You must (of course) use it when fetching the page though.
    # authentication is now handled automatically for us
    return urllib2.urlopen(theurl)

def formatVal(v):
    
    v=v.replace(",", ".")
    v=v.replace("Mb", "")
    v=v.replace("MB", "")
    v=v.replace("b", "")
    
    try:
        if v.index("Gb") > 0 :
            v=float(v.split("Gb")[0])*1024
            return v
    except ValueError:
        ''
    try:
        if v.index("GB") > 0 :
            v=float(v.split("GB")[0])*1024
            return v
    except ValueError:
        ''
    
    try:
        if v.index("Kb") > 0:
            v=float(v.split("Kb")[0])/1024
            return v
    except ValueError:
        ''
        
    try:
        if v.index("K") > 0:
            v=float(v.split("K")[0])/1024
            return v
    except ValueError:
        ''
    
    try:
        if v.index("KB") > 0:
            v=float(v.split("K")[0])/1024
            return v
    except ValueError:
        ''

    return v
     
class Jboss_Instance(models.Model):
    name = models.CharField(max_length=200)
    jmx_page = models.CharField(max_length=200)
    created_date = models.DateField(auto_now=True, auto_now_add=True)
    track_period=models.IntegerField()
    has_security = models.BooleanField(choices=((True, 'Yes'), (False, 'No')))
    has_https = models.BooleanField(choices=((True, 'Yes'), (False, 'No')))
    username = models.CharField(max_length=200, blank=True, null=True)
    password = models.CharField(max_length=200, blank=True, null=True)
    meta_data=models.CharField(max_length=5000, blank=True, null=True);
    track_threads = models.BooleanField(choices=((True, 'Yes'), (False, 'No')))
    def __unicode__(self):
        return self.name
    
signals.post_save.connect(jboss_instance_created, Jboss_Instance, dispatch_uid="jboss_observer.analyzer.models")
signals.pre_delete.connect(jboss_instance_deleted, Jboss_Instance, dispatch_uid="jboss_observer.analyzer.models")
    
class Report(models.Model):
    jboss_instance = models.ForeignKey(Jboss_Instance)
    report_date = models.CharField(max_length=20)
    mem_cur_1 = models.CharField(max_length=20)
    mem_max_1 = models.CharField(max_length=20)
    mem_cur_2 = models.CharField(max_length=20)
    mem_max_2 = models.CharField(max_length=20)
    mem_cur_3 = models.CharField(max_length=20)
    mem_max_3 = models.CharField(max_length=20)
    mem_cur_4 = models.CharField(max_length=20)
    mem_max_4 = models.CharField(max_length=20)
    mem_cur_5 = models.CharField(max_length=20)
    mem_max_5 = models.CharField(max_length=20)
    def __unicode__(self):
        return self.report_date

class Meta_Report(models.Model):
    jboss_instance = models.ForeignKey(Jboss_Instance)
    report_date = models.CharField(max_length=20)
    meta_data=models.CharField(max_length=5000, blank=True, null=True);
    meta_data_thread=models.CharField(max_length=5000, blank=True, null=True);
    def __unicode__(self):
        return self.report_date

